package com.atguigu.gmall.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.List;

@Component
public class AuthGlobalFilter implements GlobalFilter {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${authUrls.url}")
    private String authUrls;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取到请求对象
        ServerHttpRequest request = exchange.getRequest();

        //RequestPath path = request.getPath();//http://localhost/api/list/....
        String path = request.getURI().getPath(); //api/......

        //限制访问内部接口
        if(antPathMatcher.match("/**/inner/**",path)){
            ServerHttpResponse response = exchange.getResponse();
            return out(response, ResultCodeEnum.PERMISSION);
        }

        String userId = getUserId(request);
        String userTempId = getUserTempId(request);


        //token被盗用
        if("-1".equals(userId)){
            ServerHttpResponse response = exchange.getResponse();
            return out(response, ResultCodeEnum.PERMISSION);
        }

        //限制访问权限路径
        if(antPathMatcher.match("/api/**/auth/**",path)){
            if(StringUtils.isEmpty(userId)){
                ServerHttpResponse response = exchange.getResponse();
                return out(response, ResultCodeEnum.LOGIN_AUTH);
            }
        }

        //验证url
        String[] urls = authUrls.split(",");
        for (String url : urls) {
            if(path.indexOf(url)!=-1 && StringUtils.isEmpty(userId)){
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.SEE_OTHER);
                response.getHeaders().set(HttpHeaders.LOCATION,"http://www.gmall.com/login.html?originUrl=" + request.getURI());

                return response.setComplete();
            }
        }

        //将userId传递给后端
        if(!StringUtils.isEmpty(userId) || !StringUtils.isEmpty(userTempId)){
            /*request.getHeaders().set("userId",userId);
            exchange.mutate().request(request);*/
            if(!StringUtils.isEmpty(userId)){
                request.mutate().header("userId",userId).build();
            }
            if(!StringUtils.isEmpty(userTempId)){
                request.mutate().header("userTempId",userTempId).build();
            }

            return chain.filter(exchange.mutate().request(request).build());
        }
        return chain.filter(exchange);
    }

    //鉴权失败返回数据
    private Mono<Void> out(ServerHttpResponse response, ResultCodeEnum loginAuth) {
        Result<Object> result = Result.build(null, loginAuth);
        String string = JSON.toJSONString(result);
        DataBuffer wrap = response.bufferFactory().wrap(string.getBytes());
        response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
        return response.writeWith(Mono.just(wrap));
    }

    //获取用户id
    private String getUserId(ServerHttpRequest request) {
        String token = "";
        List<String> list = request.getHeaders().get("token");

        if(!CollectionUtils.isEmpty(list)){
            token = list.get(0);
        }else{
            HttpCookie httpCookie = request.getCookies().getFirst("token");
            if(httpCookie!=null){
                token = httpCookie.getValue();
            }
        }

        if(!StringUtils.isEmpty(token)){
            String loginKey = "user:login:" + token;
            String jsonStr = (String) redisTemplate.opsForValue().get(loginKey);
            JSONObject jsonObject = JSONObject.parseObject(jsonStr);
            if(jsonObject!=null){
                String ip = (String) jsonObject.get("ip");
                if(ip.equals(IpUtil.getGatwayIpAddress(request))){
                    String userId = (String) jsonObject.get("userId");
                    return userId;
                }else {
                    return "-1";
                }
            }
        }
        return "";
    }

    //获取临时id
    private String getUserTempId(ServerHttpRequest request) {
        String userTempId = "";
        List<String> list = request.getHeaders().get("userTempId");

        if(!CollectionUtils.isEmpty(list)){
            userTempId = list.get(0);
        }else{
            HttpCookie httpCookie = request.getCookies().getFirst("userTempId");
            if(httpCookie!=null){
                userTempId = httpCookie.getValue();

            }
        }
        return userTempId;
    }
}
